<?php

namespace app\shopapi\model;



use app\api\model\shop\ShopDiscountOrder;
use think\Exception;
use think\Model;


//商家账单
class ShopBills extends Model
{
    protected $name = 'shop_bills';

    // 自动写入时间戳字段
    protected $autoWriteTimestamp = 'integer';

    // 定义时间戳字段名
    protected $createTime = 'createtime';
    protected $updateTime = 'updatetime';
    protected $deleteTime = false;

    // 追加属性
    protected $append = [
        'pay_time_text'
    ];

    public $order_field = [
        'order_no' => '交易编号',
        'arrival_amount' => '收款金额',
        'service_charge' => '交易手续费',
        'discount_offer' => '折扣优惠',
        'income' => '应到账金额',
        'pay_time' => '收款时间',
        'pay_status' => '交易状态',
        'pay_type' => '收款平台',
        'consume_type' => '消费类型',
        'worker_name' => '收款员工',
        'pay_remark' => '付款备注',
        'collect_money_remark' => '收款备注',
        'account_type' => '账户类型',
        'collection_account' => '收款账户',
        'to_account_time' => '到账时间',
    ];

    public $arrival_field = [
        'order_no' => '商户名称',
        'pay_time' => '划款时间',
        'arrival_amount' => '划款金额',
        'collection_account' => '入账账户',
        'account_type' => '入账银行',
        'realname' => '开户人姓名',
        'pay_status' => '到账状态',
        'remark' => '付款备注',
    ];

    public $define_data = [
        'pay_status' => ['type' => 2, 'data' => ['未支付', '已支付']],//支付状态
        'pay_time' => ['type' => 1],//支付时间
        'consume_type' => ['type' => 2, 'data' => ['扫码买单', '折扣买单','团购']],//支付状态
        'pay_type' => ['type' => 2, 'data' => ['ALIPAY' => '支付宝', 'WECHAT' => '微信']],//退货方式
    ];
    public function getPayTimeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['pay_time']) ? $data['pay_time'] : '');
        return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
    }

    public static function calculate_discount($commission_rate)
    {
        $discount = (100-$commission_rate+$commission_rate*0.6)/100;

        return $discount;
    }

    //添加账单
    public function add($params)
    {
        $user_id = $params['user_id'];
        $shop_id = $params['shop_id'];
        $pay_price = $params['pay_price'];
        $pay_type = $params['pay_type'];
        $trans_oktime = $params['trans_oktime'];
        $consume_type = $params['consume_type'];
        $order_no = $params['order_no'];
        $service_charge = $params['service_charge'];
        //$service_charge = 0;
        $worker_id = $params['worker_id'];
        $remark = $params['remark'];
        $collect_money_remark = $params['collect_money_remark'];

        $bills_model = new ShopBills();
        //$order_no = date("Ymdhis") . sprintf("%08d", $user_id) . mt_rand(1000, 9999);
        $shop = Shop::where(['shop_id'=>$shop_id])->field('shop_id,commission_rate,bank_name,bank,bank_num,bank_card_id')->find();
        //$bank_num = substr($shop['bank_num'], 0, 4) . str_repeat("*", strlen($shop['bank_num']) - 4);
        //$collection_account = $bank_num;
        $discount_offer = 0;
        //折扣买单
        if ($consume_type==1){
            //打折后的钱  例如100元*0.98=实付了98,再拿100-98=折扣优惠
            $discount = self::calculate_discount($shop['commission_rate']);
            $discount_price = $discount*$pay_price;

            $discount_offer = $pay_price-$discount_price;
        }
        $stat_exist = ShopBillsStat::get(['shop_id'=>$shop_id,'date'=>date('Y-m-d')]);

        //$service_charge = $pay_price*0.004;

        //$arrival_amount = $pay_price-$service_charge;
        if ($pay_type=='alipay'){
            $pay_type_name = '支付宝';
        } else {
            $pay_type_name = '微信';
        }
        $arrival_amount = $pay_price;
        $income = $arrival_amount-$service_charge-$discount_offer;
        $data = [
            'user_id'=>$user_id,
            'shop_id'=>$shop_id,
            'stat_id'=>$stat_exist->stat_id,
            'arrival_amount'=>$arrival_amount,
            'service_charge'=>$service_charge,
            'discount_offer'=>$discount_offer,
            'pay_time'=>$trans_oktime,
            'pay_status'=>1,
            'pay_type'=>$pay_type,
            'pay_type_name'=>$pay_type_name,
            'consume_type'=>$consume_type,
            'order_no'=>$order_no,
            'collect_money_worker_id'=>$worker_id,
            'pay_remark'=>$remark,
            'collection_account'=>$shop['bank_num'],
            'income'=>$income,
            'to_account_time'=>'实时到账',
            'account_type'=>$shop['bank_name'],
            'bank_card_id'=>$shop['bank_card_id'],
            'collect_money_remark'=>$collect_money_remark
        ];
        $res = $bills_model->save($data);
        if ($res){
            //账单统计加上
            //收款总金额
            ShopBillsStat::where(['shop_id'=>$shop_id,'date'=>date('Y-m-d')])->setInc('total_collect_money',$pay_price);
            //收款笔数
            ShopBillsStat::where(['shop_id'=>$shop_id,'date'=>date('Y-m-d')])->setInc('total_count',1);
            //应到账金额
            ShopBillsStat::where(['shop_id'=>$shop_id,'date'=>date('Y-m-d')])->setInc('arrival_amount',$data['arrival_amount']);
            //手续费
            ShopBillsStat::where(['shop_id'=>$shop_id,'date'=>date('Y-m-d')])->setInc('service_charge',$data['service_charge']);
            //折扣优惠
            ShopBillsStat::where(['shop_id'=>$shop_id,'date'=>date('Y-m-d')])->setInc('discount_offer',$data['discount_offer']);
        }

        return $res;
    }

    //实时账单
    public function getRealtimeList($shop_id)
    {
        $where = ['shop_id'=>$shop_id];

        $lists = ShopBills::where($where)->order('pay_time desc')
            ->field('bills_id,arrival_amount,pay_type,pay_time')->limit(3)->select();

        return $lists;
    }


    //到账记录
    public function arrivalRecord($shop_id,$param)
    {

        $shop = \app\admin\model\shop\Shop::get($shop_id);
        $bank_card_id = $shop->bank_card_id;
        $start_time = isset($param['start_time']) ? strtotime($param['start_time']) : '';

        $end_time = isset($param['end_time']) ? strtotime($param['end_time']) : '';

        $consume_type = isset($param['consume_type']) ? $param['consume_type'] : 'all';//消费类型,0扫码买单,1折扣买单,2团购


        $where = ['shop_id'=>$shop_id,'bank_card_id'=>$bank_card_id];

        if ($start_time&&$end_time){
            $where['createtime'] = ['between', [$start_time, $end_time]];
        }

        if ($consume_type!='all'){
            $where['consume_type'] = $consume_type;
        }

        $lists = ShopBills::where($where)->field('bills_id,account_type,collection_account,arrival_amount,createtime')
            ->paginate(10);

        return $lists;


    }

    //到账记录导出
    public function exportArrivalRecord($shop_id,$param)
    {
        $start_time = isset($param['start_time']) ? strtotime($param['start_time']) : '';

        $end_time = isset($param['end_time']) ? strtotime($param['end_time']) : '';

        $consume_type = isset($param['consume_type']) ? $param['consume_type'] : 'all';//消费类型,0扫码买单,1折扣买单,2团购

        $where = ['shop_id'=>$shop_id];

        if ($start_time&&$end_time){
            $where['createtime'] = ['between', [$start_time, $end_time]];
        }

        if ($consume_type!='all'){
            $where['consume_type'] = $consume_type;
        }

        $shop = Shop::where(['shop_id'=>$shop_id])->field('shop_id,commission_rate,bank_name,bank,bank_num,shop_name')->find();

        $data = [
            'shop_id'=>$shop_id,
            'condition'=>json_encode($where,320),
            'status'=>0,
        ];

        $lists = ShopBills::where($where)->select();
        if (count($lists)==0)throw new Exception('无账单数据,不可下载!');
        $export_model = new ShopBillsExport();
        $export_model->save($data);

        $export_id = $export_model->id;

        $field = $this->arrival_field;

        set_time_limit(0);
        $file_name =  $shop['shop_name'].'-划款记录-'.date('YmdHis');//csv文件名
        $file_path = 'upload/bills_csv/';
        if (dir_mkdir($file_path)) {

            $file_path = $file_path . $file_name . '.csv';
            //创建一个临时csv文件
            $fp = fopen($file_path, 'w'); //生成临时文件
            fwrite($fp, chr(0xEF).chr(0xBB).chr(0xBF)); // 添加 BOM

            $field_value = [];
            $field_key = [];
            $field_key_array = [];
            //为了防止部分代码被筛选中替换, 给变量前后两边增加字符串
            foreach ($field as $k => $v) {
                $field_value[] = $v;
                $field_key[] = "{\$$k}";
                $field_key_array[] = $k;
            }

            $table_field = implode(',', $field_key_array);

            $order_table = ShopBills::where($where);

            $first_line = implode(',', $field_value);
            //写入第一行表头
            fwrite($fp, $first_line . "\n");

            $temp_line = implode(',', $field_key) . "\n";

            $table_field = '*';
            $order_table->field($table_field)->chunk(5000, function ($item_list) use ($fp, $temp_line, $field_key_array) {

                //写入导出信息
                $this->itemExport2($item_list, $field_key_array, $temp_line, $fp);
                unset($item_list);

            });

            $order_table->removeOption();
            fclose($fp);  //每生成一个文件关闭
            unset($order_table);

            //将同步导出记录状态
            $records_data = array(
                'path' => $file_path,
                'status' => 1
            );

            ShopBillsExport::update($records_data,['id'=>$export_id]);

            return true;
        } else {
            throw new \Exception('导出失败');
        }

    }

    //账单流水
    public function pages($shop_id)
    {

        $list = ShopBillsStat::where(['shop_id'=>$shop_id])->order('createtime desc')->paginate(10);
        foreach ($list as $k=>$v){
            $start_time = strtotime($v['date']);
            $end_time = strtotime($v['date'].' 23:59:59');
            $bill_lists = ShopBills::where(['shop_id'=>$shop_id])
                ->where('pay_time','between',[$start_time, $end_time])
                ->order('pay_time desc')->select();
            $list[$k]['bill_lists'] = $bill_lists;
        }
        return $list;
    }

    //账单列表
    public function getlist($shop_id,$param)
    {
        $start_time = isset($param['start_time']) ? strtotime($param['start_time']) : '';

        $end_time = isset($param['end_time']) ? strtotime($param['end_time']) : '';

        $pay_type = isset($param['pay_type']) ? $param['pay_type'] : 'all';//收款平台,wechatpay微信,alipay支付宝

        $consume_type = isset($param['consume_type']) ? $param['consume_type'] : 'all';//消费类型,0扫码买单,1折扣买单,2团购

        $collect_money_worker_id = isset($param['worker_id']) ? $param['worker_id'] : 0;//收款员工id

        $where = ['shop_id'=>$shop_id];

        if ($start_time&&$end_time){
            $where['createtime'] = ['between', [$start_time, $end_time]];
        }

        if ($pay_type!='all'){
            if ($pay_type=='wechatpay'){
                $where['pay_type'] = 'WECHAT';
            } else {
                $where['pay_type'] = 'ALIPAY';
            }
            //$where['pay_type'] = $pay_type;
        }

        if ($consume_type!='all'){
            $where['consume_type'] = $consume_type;
        }

        if ($collect_money_worker_id){
            $where['collect_money_worker_id'] = $collect_money_worker_id;
        }

        $lists = ShopBills::where($where)->select();

        $total_money = 0;//收款
        $income = 0;//到账
        $discount_offer = 0;//折扣优惠
        $service_charge = 0;//手续费
        $refund_money = 0;//退款
        foreach ($lists as $k=>$v){
            $total_money+=$v['arrival_amount'];
            $income+=$v['arrival_amount']-$v['discount_offer']-$v['service_charge'];
            $discount_offer+=$v['discount_offer'];
            $service_charge+=$v['service_charge'];
        }

        $data = [
            'count'=>count($lists),
            'total_money'=>round($total_money,2),
            'income'=>round($income,2),
            'discount_offer'=>round($discount_offer,2),
            'service_charge'=>round($service_charge,2),
            'refund_money'=>round($refund_money,2),
            'lists'=>$lists
        ];

        return $data;
    }

    //账单详情
    public function detail($bills_id)
    {
        $detail = ShopBills::get($bills_id);

        $shop_admin = ShopAdmin::get($detail->collect_money_worker_id);
        $detail->worker_name = $shop_admin?$shop_admin->realname:'';
        return $detail;
    }

    //账单导出
    public function export($shop_id,$param)
    {
        $start_time = isset($param['start_time']) ? strtotime($param['start_time']) : '';

        $end_time = isset($param['end_time']) ? strtotime($param['end_time']) : '';

        $pay_type = isset($param['pay_type']) ? $param['pay_type'] : 'all';//收款平台,wechatpay微信,alipay支付宝

        $consume_type = isset($param['consume_type']) ? $param['consume_type'] : 'all';//消费类型,0扫码买单,1折扣买单,2团购

        $collect_money_worker_id = isset($param['worker_id']) ? $param['worker_id'] : 0;//收款员工id

        $where = ['shop_id'=>$shop_id];

        if ($start_time&&$end_time){
            $where['createtime'] = ['between', [$start_time, $end_time]];
        }

        if ($pay_type!='all'){
            $where['pay_type'] = $pay_type;
        }

        if ($consume_type!='all'){
            $where['consume_type'] = $consume_type;
        }

        if ($collect_money_worker_id){
            $where['collect_money_worker_id'] = $collect_money_worker_id;
        }

        $shop = Shop::where(['shop_id'=>$shop_id])->field('shop_id,commission_rate,bank_name,bank,bank_num,shop_name')->find();

        $bank_name = $shop['bank_name'];

        $data = [
            'shop_id'=>$shop_id,
            'condition'=>json_encode($where,320),
            'status'=>0,
        ];

        $lists = ShopBills::where($where)->select();
        if (count($lists)==0)throw new Exception('无账单数据,不可下载!');

        $export_model = new ShopBillsExport();
        $export_model->save($data);

        $export_id = $export_model->id;

        //require_once(VENDOR_PATH .'/PHPExcel/Classes/PHPExcel.php');//执行期间包含并运行指定文件(通俗一点，括号内的文件会执行一遍
        $field = $this->order_field;
        set_time_limit(0);

        $file_name =  $shop['shop_name'].'-'.date('YmdHis');//csv文件名
        //dump($shop['shop_name']);die;
        $file_path = 'upload/bills_csv/';
        if (dir_mkdir($file_path)) {

            $file_path = $file_path . $file_name . '.csv';
            //创建一个临时csv文件
            $fp = fopen($file_path, 'w'); //生成临时文件
            fwrite($fp, chr(0xEF).chr(0xBB).chr(0xBF)); // 添加 BOM

            $field_value = [];
            $field_key = [];
            $field_key_array = [];
            //为了防止部分代码被筛选中替换, 给变量前后两边增加字符串
            foreach ($field as $k => $v) {
                $field_value[] = $v;
                $field_key[] = "{\$$k}";
                $field_key_array[] = $k;
            }

            $table_field = implode(',', $field_key_array);

            $order_table = ShopBills::where($where);

            $first_line = implode(',', $field_value);
            //写入第一行表头
            fwrite($fp, $first_line . "\n");

            $temp_line = implode(',', $field_key) . "\n";

            $table_field = '*';
            $order_table->field($table_field)->chunk(5000, function ($item_list) use ($fp, $temp_line, $field_key_array) {

                //写入导出信息
                $this->itemExport($item_list, $field_key_array, $temp_line, $fp);
                unset($item_list);

            });

            $order_table->removeOption();
            fclose($fp);  //每生成一个文件关闭
            unset($order_table);

            //将同步导出记录状态
            $records_data = array(
                'path' => $file_path,
                'status' => 1
            );

            ShopBillsExport::update($records_data,['id'=>$export_id]);

            return true;
        } else {
            throw new \Exception('导出失败');
        }

    }


    /**
     * 给csv写入新的数据
     * @param $item_list
     * @param $field_key
     * @param $temp_line
     * @param $fp
     */
    public function itemExport($item_list, $field_key, $temp_line, $fp)
    {

        $item_list = collection($item_list)->toArray();

        $item_list = $this->handleData($item_list, $field_key);
        foreach ($item_list as $k => $item_v) {
            $new_line_value = $temp_line;

            if ($item_v['collect_money_worker_id']){
                $shop_admin = ShopAdmin::get($item_v['collect_money_worker_id']);
                $item_v['worker_name'] = $shop_admin?$shop_admin->realname:'';
            } else {
                $item_v['worker_name'] ='';
            }

            foreach ($item_v as $key => $value) {

                //CSV比较简单，记得转义 逗号就好
                $values = str_replace(',', '\\', $value . "\t");
                $values = str_replace("\n", '', $values);
                $new_line_value = str_replace("{\$$key}", $values, $new_line_value);
            }
            //写入第一行表头
            fwrite($fp, $new_line_value);
            //销毁变量, 防止内存溢出
            unset($new_line_value);
        }
    }

    public function itemExport2($item_list, $field_key, $temp_line, $fp)
    {

        $item_list = collection($item_list)->toArray();

        $item_list = $this->handleData($item_list, $field_key);
        foreach ($item_list as $k => $item_v) {
            $new_line_value = $temp_line;

            if ($item_v['shop_id']){
                $shop = Shop::get($item_v['shop_id']);
                $item_v['realname'] = $shop?$shop->realname:'';
            } else {
                $item_v['realname'] ='';
            }

            foreach ($item_v as $key => $value) {

                //CSV比较简单，记得转义 逗号就好
                $values = str_replace(',', '\\', $value . "\t");
                $values = str_replace("\n", '', $values);
                $new_line_value = str_replace("{\$$key}", $values, $new_line_value);
            }
            //写入第一行表头
            fwrite($fp, $new_line_value);
            //销毁变量, 防止内存溢出
            unset($new_line_value);
        }
    }


    //退款
    public function refund($shop_id,$bills_id)
    {
        $detail = ShopBills::get($bills_id);

        $shop = Shop::get($detail->shop_id);

        $detail->refund_no = $this->createRefundNo($bills_id);

        $refund_no = $detail->refund_no;
        $pay_price = $detail->arrival_amount;

        if ($detail->consume_type==2){
            //团购
            $shop_order = ShopOrder::get(['lakala_order_no'=>$detail->order_no]);
            /*if ($shop_order->is_verify==1){
                throw new \Exception($refund_res['msg']);
            }*/
            $lakala_order_no = $shop_order->lakala_order_no;
            $pay_seq_no = $shop_order->pay_seq_no;
        } else {
            $discount_order = ShopDiscountOrder::get(['lakala_order_no'=>$detail->order_no]);
            $lakala_order_no = $discount_order->lakala_order_no;
            $pay_seq_no = $discount_order->pay_seq_no;
        }

        $pay_model = new \app\shopapi\model\lakala\Pay();

        $refund_res = $pay_model->refund($lakala_order_no, $refund_no,$pay_price,$pay_seq_no,$shop->member_no);

        if ($refund_res['code']==0){
            throw new \Exception($refund_res['msg']);
        }

        $detail->refund_time = time();
        $detail->refund_status = 1;
        $res = $shop->save();

        ShopBillsStat::where(['shop_id'=>$shop_id,'date'=>date('Y-m-d')])->setInc('refund_price',$pay_price);
        return $res;
    }

    /**
     * 创建退款流水号
     */
    public function createRefundNo($unique)
    {
        $no = createno('refund_no', '', $unique);
        return $no;
    }

    /**
     *  数据处理
     * @param $data
     * @param $field
     * @return array
     */
    public function handleData($data, $field)
    {
        $define_data = $this->define_data;

        foreach ($data as $k => $v) {

            //获取键
            $keys = array_keys($v);

            foreach ($keys as $key) {

                if (in_array($key, $field)) {

                    if (array_key_exists($key, $define_data)) {

                        $type = $define_data[$key]['type'];

                        switch ($type) {

                            case 1:
                                $data[$k][$key] = time_to_date($v[$key]);
                                break;
                            case 2:
                                $define_data_data = $define_data[$key]['data'];
                                $data[$k][$key] = !empty($v[$key]) ? $define_data_data[$v[$key]] : '';
                        }

                    }
                }
            }

        }
        return $data;
    }
}